package com.anycc.cloud.core.service.impl;

import com.anycc.cloud.common.dto.query.PagingRequest;
import com.anycc.cloud.common.dto.query.PagingResponse;
import com.anycc.cloud.common.exception.AnyccRuntimeException;
import com.anycc.cloud.common.util.DynamicQuery;
import com.anycc.cloud.common.util.PagingUtil;
import com.anycc.cloud.common.util.PatternUtil;
import com.anycc.cloud.core.entity.Account;
import com.anycc.cloud.core.entity.Role;
import com.anycc.cloud.core.enums.Status;
import com.anycc.cloud.core.repository.AccountRepository;
import com.anycc.cloud.core.service.AccountService;
import com.anycc.cloud.core.util.CryptoUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.List;

import static com.anycc.cloud.common.constant.CacheNameConstant.FIELD_CACHE_MENU;

/**
 * account service 实现类
 */
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountRepository accountRepository;
    @Autowired
    private CryptoUtil cryptoUtil;

    @Override
    public Account create(Account account, String confirmPassword) {
        checkPassword(account, confirmPassword);
       checkUserName(account);
        Assert.isNull(account.getId(), "新增账户时，账户ID必须为空");
        if (account.getStatus() == null) {
            account.setStatus(Status.ENABLE);
        }
        account.setPassword(cryptoUtil.decryptJsAES(account.getPassword(), account.getUsername()));
        account.setPassword(cryptoUtil.bCryptPasswordEncoder().encode(account.getPassword()));
        return accountRepository.save(account);
    }

    @Override
    @CacheEvict(value = {FIELD_CACHE_MENU},allEntries=true)//allEntries表示清除该key下所有元素
    public void delete(String id) {
        Account account = accountRepository.findById(id).orElse(null);
        assertAccountExisted(account);
        accountRepository.delete(account);
    }

    @Override
    public Account findByUsername(String username) {
        return accountRepository.findByUsername(username);
    }

    @Override
    @CacheEvict(value = {FIELD_CACHE_MENU},allEntries=true)//allEntries表示清除该key下所有元素
    public Account update(Account account) {
        Assert.notNull(account.getId(), "更新账户时，账户ID不能为空");
        checkUserName(account);
        Account dbAccount = accountRepository.findById(account.getId()).orElse(null);
        if (dbAccount == null) {
            throw new AnyccRuntimeException("core.exceptions.account.not_existed");
        }
        account.setPassword(dbAccount.getPassword());
        return accountRepository.save(account);
    }

    @Override
    public PagingResponse<Account> findByPaging(Account account, PagingRequest pagingRequest) {
        Page<Account> page = accountRepository
                .findAll(new DynamicQuery<Account>().build((predicates, root, query, cb) -> {
                    if (StringUtils.isNotBlank(account.getUsername())) {
                        predicates.add(cb.like(root.get(Account.FIELD_USER_NAME), PatternUtil.trimLike(account.getUsername())));
                    }
                }), PagingUtil.buildPageRequest(pagingRequest));
        return PagingUtil.buildPagingResponse(pagingRequest, page);
    }

    @Override
    public Account findById(String id) {
        return accountRepository.findById(id).orElse(null);
    }

    @Override
    public void deleteRole(String roleId) {
        Assert.notNull(roleId, "删除角色时，角色ID不能为空");
        List<Account> accountList = accountRepository.findByRolesId(roleId);
        if (!accountList.isEmpty()) {
            List<Account> newAccountList = filterDeletedRole(accountList, roleId);
            accountRepository.saveAll(newAccountList);
        }
    }

    private void checkPassword(Account account, String confirmPassword) {
        if (StringUtils.isBlank(account.getPassword())) {
            throw new AnyccRuntimeException("core.exceptions.account.password_required");
        } else if (!StringUtils.equals(account.getPassword(), confirmPassword)) {
            throw new AnyccRuntimeException("core.exceptions.account.confirmed_pwd_not_equal");
        }
    }

    private void checkUserName(Account account) {
        if (StringUtils.isBlank(account.getUsername())) {
            throw new AnyccRuntimeException("core.exceptions.account.name_required");
        } else {
            Account dbAccount = accountRepository.findByUsername(account.getUsername());
            if (dbAccount != null && !dbAccount.getId().equals(account.getId())) {
                throw new AnyccRuntimeException("core.exceptions.account.name_existed," + dbAccount.getUsername());
            }
        }
    }

    private void assertAccountExisted(Account account) {
        if (account == null) {
            throw new AnyccRuntimeException("core.exceptions.account.not_existed");
        }
    }

    private List<Account> filterDeletedRole(List<Account> accountList, String filterRoleId) {
        List<Account> newAccountList = new ArrayList<>(accountList.size());
        accountList.forEach(account -> {
            List<Role> newRoles = new ArrayList<>();
            account.getRoles().forEach(role -> {
                if (!StringUtils.equals(role.getId(), filterRoleId)) {
                    newRoles.add(role);
                }
            });
            account.setRoles(newRoles);
            newAccountList.add(account);
        });

        return newAccountList;
    }
}
